#include "../include/encoder/x264_encoder.h"

X264Encoder::X264Encoder(int p_width, int p_height) :
	width(p_width),
	height(p_height),
	csp(X264_CSP_I420),
	y_size(p_width*p_height),
	frame_idx(0),
	iNal(0)
{
}

X264Encoder::~X264Encoder(){

}

int X264Encoder::init() {

	pPic_in = (x264_picture_t*) malloc(sizeof(x264_picture_t));
	pPic_out = (x264_picture_t*) malloc(sizeof(x264_picture_t));
	pParam = (x264_param_t*) malloc(sizeof(x264_param_t));

	x264_param_default(pParam);
	pParam->i_width = width;
	pParam->i_height = height;

	pParam->i_csp = csp;
	x264_param_apply_profile(pParam, x264_profile_names[5]);

	pHandle = x264_encoder_open(pParam);

	x264_picture_init(pPic_out);
	x264_picture_alloc(pPic_in, csp, pParam->i_width, pParam->i_height);
	x264_encoder_headers(pHandle, &pNals, &iNal);

	return CODEC_OK;
}

int X264Encoder::encodeFrame(unsigned char* yuv_data, unsigned char* encode_buffer, int& length) {

	memcpy(pPic_in->img.plane[0], yuv_data, y_size);
	memcpy(pPic_in->img.plane[1], yuv_data + y_size, y_size/4);
	memcpy(pPic_in->img.plane[2], yuv_data + y_size*5/4, y_size/4);

	pPic_in->i_pts = frame_idx;
	int ret = x264_encoder_encode(pHandle, &pNals, &iNal, pPic_in, pPic_out);

	if (ret < 0) {
		return CODEC_ERROR_FFMPEG_ENCODER_ENCODE_FAILED;
	}

	length = 0;
	for (int j = 0; j < iNal; ++j) {
		memcpy(encode_buffer+length, pNals[j].p_payload, pNals[j].i_payload);
		length += pNals[j].i_payload;
	}

	frame_idx++;
	return CODEC_OK;
}

void X264Encoder::close() {
	x264_picture_clean(pPic_in);
	x264_encoder_close(pHandle);
	pHandle = NULL;

	free(pPic_in);
	free(pPic_out);
	free(pParam);
}
